﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LogicalComponent.util;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace TestLogicalComponent.util
{
    [TestClass]
    public class TestCoordinate
    {
        [TestMethod]
        public void TestConstructor()
        {
            Coordinate l = new Coordinate(4, 8);
            Assert.AreEqual(l.X, 4);
            Assert.AreEqual(l.Z, 8);
        }

        [TestMethod]
        public void TestSubtration()
        {
            Coordinate l1 = new Coordinate(4, 8);
            Coordinate l2 = new Coordinate(1, 3);

            Coordinate diff = l1 - l2;
            Assert.AreEqual(diff.X, 3);
            Assert.AreEqual(diff.Z, 5);
        }

        [TestMethod]
        public void TestEquivalence()
        {
            Coordinate a1 = new Coordinate(1, 2);
            Coordinate a2 = new Coordinate(1, 2);

            Coordinate b1 = new Coordinate(1, 4);
            Coordinate b2 = new Coordinate(1, 4);

            Coordinate c1 = new Coordinate(3, 4);
            Coordinate c2 = new Coordinate(3, 4);

            Tuple<Coordinate, Coordinate>[] sets = new Tuple<Coordinate, Coordinate>[] {
                    new Tuple<Coordinate, Coordinate>(a1, a2),
                    new Tuple<Coordinate, Coordinate>(b1, b2),
                    new Tuple<Coordinate, Coordinate>(c1, c2),
                                };
            for (int i = 0; i < sets.Count(); i++)
            {
                Tuple<Coordinate, Coordinate> first = sets[i];
                Assert.IsTrue(first.Item1 == first.Item2);
                Assert.IsFalse(first.Item1 != first.Item2);
                Assert.IsTrue(first.Item1.Equals(first.Item2));
                Assert.AreEqual(first.Item1, first.Item2);
                Assert.AreEqual<Coordinate>(first.Item1, first.Item2);

                Assert.IsTrue(first.Item1 == first.Item1);
                Assert.IsFalse(first.Item1 != first.Item1);
                Assert.IsTrue(first.Item1.Equals(first.Item1));
                Assert.AreEqual(first.Item1, first.Item1);
                Assert.AreEqual<Coordinate>(first.Item1, first.Item1);

                for (int j = 0; j < sets.Count(); j++)
                {
                    if (i != j)
                    {
                        Tuple<Coordinate, Coordinate> second = sets[j];
                        Assert.IsFalse(first.Item1 == second.Item1);
                        Assert.IsTrue(first.Item1 != second.Item1);
                        Assert.IsFalse(first.Item1.Equals(second.Item1));
                        Assert.AreNotEqual(first.Item1, second.Item1);
                        Assert.AreNotEqual<Coordinate>(first.Item1, second.Item1);
                    }
                }
            }
        }
        [TestMethod]
        public void TestNullEquivalence()
        {
            Coordinate real = new Coordinate(1, 1);
            Coordinate isNull = null;

            Tuple<Coordinate, Coordinate, bool>[] sets = {
                           new Tuple<Coordinate, Coordinate, bool>(real, isNull, false),
                           new Tuple<Coordinate, Coordinate, bool>(isNull, isNull, true),
                                                         };

            foreach (Tuple<Coordinate, Coordinate, bool> set in sets)
            {
                String item1String = "null";
                if (set.Item1 != null)
                {
                    item1String = "not null";
                }
                Assert.AreEqual(set.Item1 == set.Item2, set.Item3); 
                Assert.AreEqual(set.Item2 == set.Item1, set.Item3);
                if (set.Item1 != null)
                {
                    Assert.AreEqual(set.Item1.Equals(set.Item2), set.Item3);
                }
                Assert.AreEqual(set.Item2 != set.Item1, !set.Item3, 
                                string.Format("item1 {0}, item2 {1}", item1String, "null")); 
                Assert.AreEqual(set.Item1 != set.Item2, !set.Item3); 
            }
        }

        [TestMethod]
        public void TestSerialize()
        {
            Coordinate[] coordinates = { new Coordinate(-2, 5),
                                         new Coordinate(0, 0),
                                       };
            foreach (Coordinate c in coordinates)
            {
                IFormatter bin = new BinaryFormatter();
                MemoryStream s = new MemoryStream();
                bin.Serialize(s, c);
                s.Position = 0;
                Coordinate deserialized = (Coordinate)bin.Deserialize(s);
                Assert.AreEqual<Coordinate>(c, deserialized);
            }
        }
        
    }
}
